package edu.sjtu.grid.workflow.facts;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Element;

import edu.sjtu.grid.workflow.Util;
import edu.sjtu.grid.workflow.schedule.ScheduleBase.ScheduleType;

public class Runs {
	private Facts facts = null;
	private List<Run> runList = null;
	
	public Run getCheapestRun()
	{
		for(Run run : this.runList)
		{
			if(run.getScheduleType() == ScheduleType.Cheapest)
				return run;
		}
		return null;
	}
	
	public Run getHEFTRun()
	{
		for(Run run : this.runList)
		{
			if(run.getScheduleType() == ScheduleType.HEFT)
				return run;
		}
		return null;
	}
	
	public List<Run> getHeuristicSearchRunList()
	{
		List<Run> list = new ArrayList<Run>();
		for(Run run : this.runList)
		{
			if(run.getScheduleType() == ScheduleType.HeuristicSearch)
				list.add(run);
		}
		Collections.sort(list, new RunDeadlineComparator());
		return list;
	}
	
	public List<Run> getHeuristicSearchRunList_AvgCost()
	{
		List<Run> list = new ArrayList<Run>();
		for(Run run : this.runList)
		{
			if(run.getScheduleType() == ScheduleType.HeuristicSearch_AvgCost)
				list.add(run);
		}
		Collections.sort(list, new RunDeadlineComparator());
		return list;
	}
	
	public List<Run> getHeuristicSearchRunList_AvgCost_Wait()
	{
		List<Run> list = new ArrayList<Run>();
		for(Run run : this.runList)
		{
			if(run.getScheduleType() == ScheduleType.HeuristicSearch_AvgCost_Wait)
				list.add(run);
		}
		Collections.sort(list, new RunDeadlineComparator());
		return list;
	}
	
	public List<Run> getHeuristicSearchRunList_InitialCost()
	{
		List<Run> list = new ArrayList<Run>();
		for(Run run : this.runList)
		{
			if(run.getScheduleType() == ScheduleType.HeuristicSearch_InitialCost)
				list.add(run);
		}
		Collections.sort(list, new RunDeadlineComparator());
		return list;
	}
	
	private class RunDeadlineComparator implements Comparator<Run>
	{

		@Override
		public int compare(Run arg0, Run arg1) {
			if(arg0.getDeadline() == null || arg1.getDeadline() == null)
				return 0;
			else if(arg0.getDeadline() > arg1.getDeadline())
				return 1;
			else 
				return -1;
		}
		
	}
	
	public boolean hasRun(ScheduleType type, double deadline)
	{
		for(Run run : this.runList)
		{
			if(run.getScheduleType() == type
				&& run.getDeadline() != null
				&& Util.isEqual(run.getDeadline(), deadline))
				return true;
		}
		return false;
	}
	
	public boolean hasRunSuccess(ScheduleType type, double deadline)
	{
		for(Run run : this.runList)
		{
			if(run.getScheduleType() == type
				&& run.getDeadline() != null
				&& Util.isEqual(run.getDeadline(), deadline)
				&& run.isSucc())
				return true;
		}
		return false;
	}
	
	public List<Run> getMDPSearchRunList()
	{
		List<Run> list = new ArrayList<Run>();
		for(Run run : this.runList)
		{
			if(run.getScheduleType() == ScheduleType.MDPSearch)
				list.add(run);
		}
		Collections.sort(list, new RunDeadlineComparator());
		return list;
	}
	
	public void addRun(Run run)
	{
		this.runList.add(run);
	}
	
	public String toXML(String prefix, String tab)
	{
		StringBuilder s = new StringBuilder();
		s.append(prefix + "<runs>\n");
		for(Run run : runList)
			s.append(run.toXML(prefix+tab, tab));
		s.append(prefix + "</runs>\n");
		return s.toString();
	}
	
	@SuppressWarnings("unchecked")
	public Runs(Facts facts, Element eRuns)
	{
		this.facts = facts;
		this.runList = new ArrayList<Run>();
        if(eRuns == null)
        	return;
        
        for (Iterator<Element> i = eRuns.elementIterator("run"); i.hasNext(); ) {
            Element eRun= (Element)i.next();
            this.runList.add(new Run(this.facts, eRun));
        }
	}
        
	public String toString()
	{
		StringBuilder s = new StringBuilder();
		s.append("----------runs----------\n");
		for(Run run : runList)
			s.append(run.toString());
		return s.toString();
	}
	
}
